﻿/**********************************************
* 作    者：YuBing
* 创建日期：2009年07月07日
* 描    述：为 Sql Server 提供批量处理操作。
* 修改日期：2009年07月07日
***********************************************/
using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;


namespace Meqs.Logic.Batcher
{
    /// <summary>
    /// 为 Sql Server 提供批量处理操作。
    /// </summary>
    public class SqlBatcher : IBatcher
    {
        private readonly MethodInfo _addToBatch;
        private readonly MethodInfo _clearBatch;
        private readonly MethodInfo _initializeBatching;
        private readonly MethodInfo _executeBatch;
        private SqlDataAdapter _adapter;
        private bool _started;

        /// <summary>
        /// 构造一个新的 SqlBatcher。
        /// </summary>
        public SqlBatcher()
        {
            Type type = typeof(SqlDataAdapter);
            _addToBatch = type.GetMethod("AddToBatch", BindingFlags.NonPublic | BindingFlags.Instance);
            _clearBatch = type.GetMethod("ClearBatch", BindingFlags.NonPublic | BindingFlags.Instance);
            _initializeBatching = type.GetMethod("InitializeBatching", BindingFlags.NonPublic | BindingFlags.Instance);
            _executeBatch = type.GetMethod("ExecuteBatch", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        /// <summary>
        /// 获得批处理是否正在批处理状态。
        /// </summary>
        public bool Started
        {
            get { return _started; }
        }

        /// <summary>
        /// 开始批处理。
        /// </summary>
        /// <param name="connection">连接。</param>
        /// <param name="type">
        /// Command类型:
        /// INSERT
        /// UPDATE
        /// DELETE
        /// </param>
        public void StartBatch(IDbConnection connection, string type)
        {
            if (_started) return;
            SqlCommand command = new SqlCommand();
            command.Connection = (SqlConnection) connection;
            _adapter = new SqlDataAdapter();

            if (type.ToUpper() == "INSERT")
            {
                _adapter.InsertCommand = command;
            }
            else if (type.ToUpper() == "UPDATE")
            {
                _adapter.UpdateCommand = command;
            }
            else if (type.ToUpper() == "DELETE")
            {
                _adapter.DeleteCommand = command;
            }
            else
            {
                _started = false;
                return;
            }

            _initializeBatching.Invoke(_adapter, null);
            _started = true;
        }

        /// <summary>
        /// 开始批处理。
        /// </summary>
        /// <param name="connection">连接。</param>
        /// <param name="tran"></param>
        /// <param name="type">
        /// Command类型:
        /// INSERT
        /// UPDATE
        /// DELETE
        /// </param>
        public void StartBatch(IDbConnection connection, IDbTransaction tran, string type)
        {
            if (_started) return;
            SqlCommand command = new SqlCommand();
            command.Connection = (SqlConnection) connection;
            command.Transaction = (SqlTransaction) tran;
            _adapter = new SqlDataAdapter();

            if (type.ToUpper() == "INSERT")
            {
                _adapter.InsertCommand = command;
            }
            else if (type.ToUpper() == "UPDATE")
            {
                _adapter.UpdateCommand = command;
            }
            else if (type.ToUpper() == "DELETE")
            {
                _adapter.DeleteCommand = command;
            }
            else
            {
                _started = false;
                return;
            }

            _initializeBatching.Invoke(_adapter, null);
            _started = true;
        }

        /// <summary>
        /// 添加批命令。
        /// </summary>
        /// <param name="command">命令</param>
        public void AddToBatch(IDbCommand command)
        {
            if (!_started) throw new InvalidOperationException();
            _addToBatch.Invoke(_adapter, new object[] { command });
        }

        /// <summary>
        /// 执行批处理。
        /// </summary>
        /// <returns>影响的数据行数。</returns>
        public int ExecuteBatch()
        {
            if (!_started) throw new InvalidOperationException();
            return (int)_executeBatch.Invoke(_adapter, null);
        }

        /// <summary>
        /// 结束批处理。
        /// </summary>
        public void EndBatch()
        {
            if (_started)
            {
                ClearBatch();
                _adapter.Dispose();
                _adapter = null;
                _started = false;
            }
        }

        /// <summary>
        /// 清空保存的批命令。
        /// </summary>
        public void ClearBatch()
        {
            if (!_started) throw new InvalidOperationException();
            _clearBatch.Invoke(_adapter, null);
        }
    }
}
